package com.iplant.aps.service.po.sch;

import com.iplant.aps.service.apsenum.aps.APSShiftPeriod;
import com.iplant.aps.service.po.aps.APSCapacityUsed;
import com.iplant.aps.service.po.aps.APSTaskPart;
import com.iplant.aps.service.po.aps.APSTaskPartPoint;
import com.iplant.aps.service.po.oms.OMSOrder;
import com.iplant.aps.serviceImpl.utils.aps.iPlantSchedulePartPointTools;
import com.iplant.aps.serviceImpl.utils.aps.iPlantSchedulePartTools;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.pdm.service.po.bop.FPCRoutePart;
import com.iplant.pdm.service.po.bop.FPCRoutePartPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

public class APSMarginCapacityAndResult {

    public boolean ShiftEnable = false;

    private static final Logger logger = LoggerFactory.getLogger(APSMarginCapacityAndResult.class);

    public Map<Integer, APSMarginEntityCapacity> MarginEntityCapacityMap = new HashMap<>();

    public Map<Integer, Map<String, Float>> ResultMap = new HashMap<>();


    public Map<Integer, Map<String, List<APSCapacityUsed>>> ResultUsedMap(int wProductID) {
        Map<Integer, Map<String, List<APSCapacityUsed>>> wResult = new HashMap<>();
        for (Integer wKey : MarginEntityCapacityMap.keySet()) {
            wResult.put(wKey, MarginEntityCapacityMap.get(wKey).DayUseCapacityMap(wProductID));
        }
        return wResult;
    }

    public Map<Integer, Map<String, Float>> TotalResultMap = new HashMap<>();


    public APSMarginCapacityAndResult() {
    }

    public APSMarginCapacityAndResult(Map<Integer, APSMarginEntityCapacity> wMarginEntityCapacityMap,boolean wShiftEnable) {
        this.MarginEntityCapacityMap = wMarginEntityCapacityMap;
        this.ShiftEnable = wShiftEnable;
    }

    public void AddToTotal() {

        if (this.TotalResultMap == null)
            this.TotalResultMap = new HashMap<>();


        if (ResultMap != null) {
            for (Integer wKey : this.ResultMap.keySet()) {
                //增加排程计划
                if (!this.TotalResultMap.containsKey(wKey))
                    this.TotalResultMap.put(wKey, new HashMap<String, Float>());

                for (String wString : this.ResultMap.get(wKey).keySet()) {

                    if (!this.TotalResultMap.get(wKey).containsKey(wString)) {
                        this.TotalResultMap.get(wKey).put(wString, this.ResultMap.get(wKey).get(wString));
                    } else {
                        this.TotalResultMap.get(wKey).put(wString,
                                this.TotalResultMap.get(wKey).get(wString) + this.ResultMap.get(wKey).get(wString));
                    }
                }
            }

        }

        ResultMap = new HashMap<>();
    }


    /**
     * 获取已确定计划的产量
     *
     * @param wKey
     * @param wDate
     * @return
     */
    public float getCapacity(int wKey, Calendar wDate) {
        if (!ResultMap.containsKey(wKey))
            return 0;
        String wDateString = StringUtils.parseCalendarToString(wDate, "yyyy-MM-dd");
        if (ResultMap.get(wKey).containsKey(wDateString))
            return ResultMap.get(wKey).get(wDateString);
        return 0;
    }

    public APSMarginCapacityAndResult Clone() {
        APSMarginCapacityAndResult wAPSMarginCapacityAndResult = new APSMarginCapacityAndResult();

        for (Integer wKey : MarginEntityCapacityMap.keySet()) {
            wAPSMarginCapacityAndResult.MarginEntityCapacityMap.put(wKey, MarginEntityCapacityMap.get(wKey).Clone());
        }
        for (Integer wKey : ResultMap.keySet()) {
            wAPSMarginCapacityAndResult.ResultMap.put(wKey, new HashMap<String, Float>(ResultMap.get(wKey)));
        }
        return wAPSMarginCapacityAndResult;
    }

    public void Set(APSMarginCapacityAndResult wAPSMarginCapacityAndResult) {
        if (wAPSMarginCapacityAndResult == null)
            return;
        this.MarginEntityCapacityMap = wAPSMarginCapacityAndResult.MarginEntityCapacityMap;
        this.ResultMap = wAPSMarginCapacityAndResult.ResultMap;
    }

    public void ClearResult() {
        ResultMap = new HashMap<>();
        TotalResultMap = new HashMap<>();

        for (APSMarginEntityCapacity wAPSMarginEntityCapacity : MarginEntityCapacityMap.values()) {
            wAPSMarginEntityCapacity.ClearResult();
        }
    }


    /**
     * 获取剩余产能
     *
     * @param wEntityIDList
     * @return
     */
    public float GetEntityCapacity(List<Integer> wEntityIDList, int wProductID, Calendar wDate) {
        if (this.MarginEntityCapacityMap == null || this.MarginEntityCapacityMap.size() == 0)
            return 0;
        float wResult = 0;
        String wDateString = StringUtils.parseCalendarToString(wDate, "yyyy-MM-dd");
        for (Integer wEntityID : wEntityIDList) {
            if (!this.MarginEntityCapacityMap.containsKey(wEntityID))
                continue;

            if (this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap == null || this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.size() == 0
                    || !this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.containsKey(wDateString)) {
                continue;
            }
            wResult += this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.get(wDateString).getCapacity(wProductID, wDate, ShiftEnable);
        }
        return wResult;
    }

    /**
     * 使用剩余产能
     *
     * @param wEntityIDList
     * @return
     */
    public float UseCapacity(List<Integer> wEntityIDList,
                             int wProductID,int wPartPointID, Calendar wDate, float wUsedNum) {
        if (this.MarginEntityCapacityMap == null || this.MarginEntityCapacityMap.size() == 0)
            return wUsedNum;
        String wDateString = StringUtils.parseCalendarToString(wDate, "yyyy-MM-dd");
        for (Integer wEntityID : wEntityIDList) {
            if (!this.MarginEntityCapacityMap.containsKey(wEntityID))
                continue;

            if (this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap == null || this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.size() == 0
                    || !this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.containsKey(wDateString)) {
                continue;
            }
            wUsedNum -= this.MarginEntityCapacityMap.get(wEntityID).DayCapacityMap.get(wDateString).UseCapacity(wProductID,wPartPointID, wUsedNum, wDate, ShiftEnable);
            if (wUsedNum <= 0)
                break;
        }

        if (wUsedNum > 0) {
            logger.info("UseCapacity Has Margin error: Date:{0} ProductID:{1},EntityIDList", wDateString, wProductID, StringUtils.Join(",", wEntityIDList));
        }
        return wUsedNum;
    }

    public void AddResult(int wKey, Calendar wDate, float wMarginCapacity) {

        String wDateString = StringUtils.parseCalendarToString(wDate, "yyyy-MM-dd");
        //增加排程计划
        if (!this.ResultMap.containsKey(wKey))
            this.ResultMap.put(wKey, new HashMap<String, Float>());

        if (!this.ResultMap.get(wKey).containsKey(wDateString)) {
            this.ResultMap.get(wKey).put(wDateString, wMarginCapacity);
        } else {
            this.ResultMap.get(wKey).put(wDateString,
                    wMarginCapacity + this.ResultMap.get(wKey).get(wDateString));
        }


    }


    public List<APSTaskPart> CreateAPSTaskPartList(BMSEmployee wLoginUser, APSShiftPeriod wAPSShiftPeriod, OMSOrder wOMSOrder, Map<Integer, FPCRoutePart> wOrderRoutePartMap) {

        List<APSTaskPart> wResult = new ArrayList<>();

        wResult = iPlantSchedulePartTools.getInstance().CreateAPSTaskPartList(wLoginUser, wAPSShiftPeriod, wOMSOrder, wOrderRoutePartMap, this.ResultUsedMap(wOMSOrder.ProductID));

        this.ClearResult();
        return wResult;
    }

    public List<APSTaskPartPoint> CreateAPSTaskPartPointList(BMSEmployee wLoginUser, APSShiftPeriod wAPSShiftPeriod, OMSOrder wOMSOrder,
                                                             Map<Integer, FPCRoutePartPoint> wOrderRoutePartMap) {
        List<APSTaskPartPoint> wResult = new ArrayList<>();

        wResult = iPlantSchedulePartPointTools.getInstance().CreateAPSTaskPartPointList(wLoginUser, wAPSShiftPeriod, wOMSOrder, wOrderRoutePartMap, this.ResultUsedMap(wOMSOrder.ProductID));

        this.ClearResult();
        return wResult;
    }

    public List<APSTaskPartPoint> CreateAPSTaskPartPointList(BMSEmployee wLoginUser, APSShiftPeriod wAPSShiftPeriod, APSTaskPart wAPSTaskPart,
                                                             Map<Integer, FPCRoutePartPoint> wOrderRoutePartMap) {
        List<APSTaskPartPoint> wResult = new ArrayList<>();

        wResult = iPlantSchedulePartPointTools.getInstance().CreateAPSTaskPartPointList(wLoginUser, wAPSShiftPeriod, wAPSTaskPart, wOrderRoutePartMap, this.ResultUsedMap(wAPSTaskPart.ProductID));

        this.ClearResult();
        return wResult;
    }


}
